<?php
// +----------------------------------------------------------------------
// | 订单管理
// +----------------------------------------------------------------------
namespace app\common\model;
use think\Model;
use think\Validate;
use think\facade\Log;
use base\pay\WxApi;
use base\pay\AliPayApi;
use base\other\Strings;

//订单关闭时间
//getSystem("buess_order_pay_time");

class Order extends Model
{
	use \app\common\modelMethod\Order;
	
	//隐藏字段
	protected $hidden = ['is_del','is_del','is_system_del','is_remind'];
	
	//事件观察
	protected static function init(){
    	self::event('after_update', function ($data) {
    		if( $data->is_brokerage==0 && $data->is_pay == 1){
    			model('order')->grantOrderProfit($data);
    		}
        });
    }
    
	// 自动完成
	protected $insert = ['order_no'];
	protected function setOrderNoAttr($value='') {
		return $value ?: Strings::createOrderNo();
    }
    protected function getInfoAttr($value) {
		return json_decode($value,true);
    }
    
	//关联用户信息，一对一关联
	public function userInfo(){
        return $this->hasOne('user','id','uid')->bind([
        	'user_nickname'=>'nickname'
        ]);
    }
	//关联店铺信息，一对一关联
	public function shopInfo(){
        return $this->hasOne('shop','id','shop_id')->bind([
        	'shop_img'=>'img',
        	'shop_name'=>'name'
        ]);
    }
	//关联优惠券信息，一对一关联
	public function couponInfo(){
        return $this->hasOne('coupon_user','id','coupon_id')->bind([
        	'coupon_name'=>'coupon_name'
        ]);
    }
	//关联订单商品，一对多关联
	public function goodsList(){
        return $this->hasMany('orderGoods','order_id');
    }
	//关联评论表，一对多关联
	public function commentList(){
        return $this->hasMany('goodsReply','order_id');
    }
	/**
    * 付款方式
    */
	protected static $payType = [
	    'wx' => '微信支付', 
	    'balance' => '余额支付',
	    'brokerage' => '佣金支付',
	    'alipay' => '支付宝',
	    'offline'=>'线下支付'
    ];
	/**
    * 配送方式
    */
	protected static $deliveryType = [
		'0' => '上门自取', 
	    '1' => '快递发货', 
	    '2' => '上门自取'
    ];
	
	
	
	// -----------------------
	// 方法-------↓-- -------
	// -----------------------
	/**
     * 获取订单列表
     * @param type $id
     * @return type
     */
	public function getList($where=[])
    {
    	$model = new self;
		$model = $model->with(['goodsList','shopInfo']);
		$model = $model->where($where);
		$model = $model->where('is_del',0);
		$model = $model->field('id,order_no,shop_id,type');
		$model = $model->field('goods_num,total_price,pay_price');
		$model = $model->field('coupon_price,status,is_pay,pay_type');
		$model = $model->field('remark,refund_status,use_integral');
		$model = $model->field('delivery_time,delivery_type,add_time');
		$model = $model->page(input('pageIndex') ?: 1,input('pageSize') ?: 20);
		$model = $model->order('add_time','desc');
		$result = $model->select();
		foreach ($result as $key => $order) {
			$order = $this->tidyOrder($order);
		}
		return $result;
    }
	
	/**
     * 订单详情
     * @return type
     */
	public function details($id)
    {
    	$model = new self;
		$model = $model->where( mb_strlen($id) > 10 ? 'order_no' : 'id',$id);
		$model = $model->field('*');
		if( ! $order = $model->find() ){
			throw new \think\Exception('订单不存在！');
		}
		
		$order ->comment_list = $order ->commentList()->group('order_id')->select();
		
		//验证是否已支付
		if($order['is_pay'] == 0 &&  in_array($order['pay_type'], ['wx','wx_applets','wx_h5'])){
			$is_pay  = WxApi::orderQuery( $order['order_no'] );
			if( $is_pay && self::paySuccess($order['order_no'],$order['pay_type']) ){
				$order['is_pay'] = 1;
				$order['pay_time'] = date("Y-m-d H:i:s");
			}
		}
		
		return $this->tidyOrder( $order );
    }
	
	/**
     * 生成确认订单信息
     * @param type $id
     * @return type
     */
    //获取确认信息页前的方法
    protected  $confirm_is_bill = 0;
    protected  $confirm_delivery_type = 1;
    protected  $confirm_activity_id = 0;
    protected  $confirm_address_id = 0;
    protected  $confirm_coupon_id = 0;
    //是否开单
    public function setBill($is=0){ $this->confirm_is_bill = $is; return $this; }
    //设置配送类型
    public function setDeliveryType($is=1){ $this->confirm_delivery_type = $is; return $this;  }
    //设置活动
    public function setActivity($is=0){ $this->confirm_activity_id = $is; return $this;  }
    //设置地址
    public function setAddress($is=0){ $this->confirm_address_id = $is; return $this;  }
    //设置优惠券
    public function setCoupon($is=0){ $this->confirm_coupon_id = $is; return $this;  }
    //获取确认页信息
	public  function confirm($cartIds,$userInfo=null)
    {
    	$shopId =  request()->shopId;
    	$userInfo = $userInfo ?: request()->userInfo;
    	$couponId =  $this->confirm_coupon_id;
    	$addressId =  $this->confirm_address_id;
    	$activityId =  $this->confirm_activity_id;
    	$deliveryType =  $this->confirm_delivery_type;
    		
    	$uid = $userInfo['id'];
    	
		// TODO 地址信息
		$addressInfo = model('UserAddress')->getUserDefaultAddress($uid,$addressId);
		
    	// TODO 获取用户购物车列表
		$cartInfo = model('ShopCart')->getUserGoodsCartList($uid,$cartIds,$userInfo);
		if( !$this->confirm_is_bill && count( array_unique(array_column($cartInfo, 'give_type')) ) > 1 ){
			throw new \think\Exception('不能同时选择不同配送方式的商品 !');
    	}
		
		// TODO 获取积分信息, 跨店不抵扣
		if($shopId != $userInfo['shop_id']){
			$integralInfo['useIntegral'] = 0;
			$integralInfo['inteBili'] = 0;
			$integralInfo['deductPrice'] = 0;
			$integralInfo['msg'] = '';
		}else{
			$integralInfo = $this->getIntegralInfo($userInfo,$cartInfo);	
		}
		
		// TODO 获取购物车赠送金额可抵扣, 跨店不抵扣
		if($shopId != $userInfo['shop_id']){
			$balanceInfo['userGiftBalance'] = 0;
			$balanceInfo['deductPrice'] = 0;
			$balanceInfo['msg'] = '';
		}else{
			$balanceInfo = $this->getDeductBalance($userInfo,$cartInfo);
		}
		
		
		// TODO 获取购物车价格组
		$prices = $this->getPriceGroup($userInfo,$cartInfo,$addressInfo);
		if($deliveryType==0 || $this->confirm_is_bill)  $prices['freightPrice'] = 0;
		
		// TODO 获取购物车返现组
		$reappeGroup = $this->getReappeGroup($cartInfo,$uid);
		
		// TODO 获取可用的优惠券
		$couponList = model('CouponUser')
			->setGroup(true)
			->beUsableCoupon($uid,$cartInfo,$prices['totalPrice']);
		$couponInfo ='';
        if($couponId) {
			foreach ($couponList as $key => $value) {
				if( $value['id'] == $couponId ){  $couponInfo = $value; }
			}
			if( !$couponInfo ) throw new \think\Exception('选择的优惠劵无效,或不满足条件,或已过期!');
        }
        
      	// TODO 获取可用的满减满折活动列表
		$activityList = model('ActivityDiscount')->beUsableActivity($cartInfo,$prices['totalPrice'],$shopId);
        $activityInfo = '';
        if (!$activityId) {
        	$activityInfo = $activityList[0];
        }else{
        	foreach ($activityList as $key => $value) {
				if( $value['id'] == $activityId ){  $activityInfo = $value; }
			}
			if( !$activityInfo ) throw new \think\Exception('选择的活动无效,或不满足条件,或已过期!');
        }
        
        //TODO 计算抵扣价格 - 得出付款价格
        //1.积分抵扣
        if($integralInfo['deductPrice'] > 0){
        	$prices['payPrice'] = bcsub($prices['payPrice'],$integralInfo['deductPrice'], 2);
			$prices['deductPrice'] = bcadd($prices['deductPrice'],$integralInfo['deductPrice'], 2); 
			$prices['payPrice'] = $prices['payPrice'] < 0 ? 0 : $prices['payPrice'];
        }
        //2.赠送余额抵扣
        if($balanceInfo['deductPrice'] > 0){
        	if( $balanceInfo['deductPrice'] > $prices['payPrice'] ){
	        	$balanceInfo['deductPrice'] = $prices['payPrice'];
	        	$balanceInfo['msg'] = "共使用".$prices['payPrice']."赠送余额抵扣".$prices['payPrice']."元";
	        	$prices['deductPrice'] = bcadd($prices['deductPrice'],$balanceInfo['deductPrice'], 2);
	        	$prices['payPrice'] = 0;
	        }else{
	        	$prices['payPrice'] = bcsub($prices['payPrice'],$balanceInfo['deductPrice'], 2);
				$prices['deductPrice'] = bcadd($prices['deductPrice'],$balanceInfo['deductPrice'], 2); 
				$prices['payPrice'] = $prices['payPrice'] < 0 ? 0 : $prices['payPrice'];
	        }
        }
        //3.优惠券抵扣
        if($couponInfo){
        	if( $couponInfo['type'] == '满折' ){
        		$fracture = $couponInfo['fracture'];
        		$fracture = $fracture <= 0 ? 10 : ($fracture >10 ? 10 : $fracture);
        		$couponInfo['price'] = $prices['payPrice'] - $prices['payPrice'] * ( $fracture / 10 );
     		}
     		$prices['payPrice'] = bcsub($prices['payPrice'],$couponInfo['price'], 2);
			$prices['deductPrice'] = bcadd($prices['deductPrice'],$couponInfo['price'], 2); 
			$prices['payPrice'] = $prices['payPrice'] < 0 ? 0 : $prices['payPrice'];
        }
        //4.满减活动抵扣
        if($activityInfo){
        	$benefit_money = $activityInfo['benefit_money'];
        	if($activityInfo['benefit_mode'] == 2){
        		$discount = $activityInfo['benefit_discount'] <=0 ? 10 : $activityInfo['benefit_discount'];
        		$discount = $discount > 10 ? 10 : $discount;
        		$benefit_money = $prices['payPrice'] - $prices['payPrice'] * ($discount / 10);
     		}
     		$activityInfo['deductPrice'] = $benefit_money;
     		$prices['payPrice'] = bcsub($prices['payPrice'],$benefit_money, 2);
			$prices['deductPrice'] = bcadd($prices['deductPrice'],$benefit_money, 2); 
     		$prices['payPrice'] = $prices['payPrice'] < 0 ? 0 : $prices['payPrice'];
        }
        //5.余额抵扣
        $amountInfo = ['deductPrice'=>0,'msg'=>"共使用0余额抵扣0元"];
        if( $this->confirm_is_bill && $userInfo['balance'] > 0 && $prices['payPrice'] > 0){
        	if($userInfo['balance'] > $prices['payPrice']){
        		$amountInfo['deductPrice'] = $prices['payPrice'];
	        	$amountInfo['msg'] = "共使用".$prices['payPrice']."余额支付".$prices['payPrice']."元";
	        	//$prices['deductPrice'] = bcadd($prices['deductPrice'],$prices['payPrice'], 2);
	        	//$prices['payPrice'] = 0;
        	}else{
        		$amountInfo['deductPrice'] = $userInfo['balance'];
	        	$amountInfo['msg'] = "共使用".$userInfo['balance']."余额支付".$userInfo['balance']."元";
	        	//$prices['deductPrice'] = bcadd($prices['deductPrice'],$amountInfo['deductPrice'], 2); 
        		//$prices['payPrice'] = bcsub($prices['payPrice'],$amountInfo['deductPrice'], 2);
				//$prices['payPrice'] = $prices['payPrice'] < 0 ? 0 : $prices['payPrice'];
        	}
        }
        //5.添加运费
        $prices['payPrice'] =  round($prices['payPrice'] + $prices['freightPrice'],2);
        $prices['totalPrice'] = $prices['totalPrice'] + $prices['freightPrice'];
		
		
		// TODO 数据整合
        $data['addressInfo'] = $addressInfo;
        $data['cartInfo'] = $cartInfo;
        $data['couponList'] = $couponList;
        $data['activityList'] = $activityList;
		$data['priceGroup'] = $prices;
		$data['reappeGroup'] = $reappeGroup;
        $data['numGroup'] = [
        	"cartCount" => count($cartInfo),
        	"goodsCount" => array_sum(array_column($cartInfo, 'cart_num'))
        ];
		$data['integralInfo'] = $integralInfo;
		$data['balanceInfo'] = $balanceInfo;
		$data['amountInfo'] = $amountInfo;
        $data['couponInfo'] = $couponInfo;
        $data['activityInfo'] = $activityInfo;
        $data['deliveryType'] = $deliveryType;
		
		//TODO 当前用户信息
        $data['userInfo'] = [
        	'id'=>$userInfo['id'],
        	'integral'=>$userInfo['integral'],
        	'balance'=>$userInfo['balance'],
        	'balance_gift'=>$userInfo['balance_gift'],
        	'brokerage'=>$userInfo['brokerage'],
        	'is_partner'=>$userInfo['is_partner'],
        	'level_name'=>$userInfo['vip_info']['level_name'],
        	'discounts'=>$userInfo['vip_info']['discounts'],
        	'shop_id'=> $userInfo['shop_id']
        ];
        
        //TODO 当前店铺信息
        $data['shopInfo']= model('shop')
	        ->field("id,name,contacts,phone,region,address_detail,img,latitude,longitude")
	        ->field("(balance - lock_balance) as balance")
	        ->get( $shopId );
	        
		//TODO 缓存订单并取得orderKey
		$data['orderKey'] = $this->cacheOrderInfo($uid,$data,600);
		
		//TODO 返回
		return $data;
    }
	
	
	/**
     * 生成订单
     * @param type $id
     * @return type
     */
    //创建订单前的方法
    protected  $create_order_mark = '';
    protected  $create_order_pay_type = 'wx';
    protected  $create_order_bill_no = 0;
    protected  $create_order_bill_id = 0;
    protected  $create_order_bill_identity = 0;
    //设置订单备注信息
    public function setMark($str=''){ $this->create_order_mark = $str; return $this; }
    //设置付款类型
    public function setPayType($str=''){ $this->create_order_pay_type = $str; return $this; }
    //设置开单人id
    public function setBillId($int=0){ $this->create_order_bill_id = $int; return $this; }
    //设置开单身份
    public function setBillIdentity($int=0){ $this->create_order_bill_identity = $int; return $this; }
    //获取确认页信息
	public  function createOrder($orderKey)
    {
    	$mark = $this->create_order_mark;
    	$payType = $this->create_order_pay_type;
    	$billId = $this->create_order_bill_id;
    	$billIdentity = $this->create_order_bill_identity;
    	$billIdentity = $this->create_order_bill_identity;
    	
    	//TODO 效验支付方式
		if (!array_key_exists($payType, self::$payType)) {
	   		throw new \think\Exception('选择支付方式有误!');
		}
    	
		//TODO 效验确认页订单是否过期
        if ( !$cacheOrderInfo = self::getCacheOrderInfo($orderKey) ){
        	throw new \think\Exception('订单信息已过期,请刷新当前页面！');
        }
        
        //TODO 获取用户信息
        if ( !$userInfo = $cacheOrderInfo['userInfo'] ){
        	throw new \think\Exception('订单信息异常错误！');
        }
      
		//TODO 购物车信息
		if(!count($cartInfo = $cacheOrderInfo['cartInfo'])){
			\Db::rollback();
			throw new \think\Exception('购物车已下单或不存在!');
		}
		
		\Db::startTrans();
		try {
			
			$uid = $userInfo['id'];
			 
			//TODO 获取缓存的订单信息租
	        $priceGroup = $cacheOrderInfo['priceGroup'];    			//订单价格组
	        $reappeGroup = $cacheOrderInfo['reappeGroup'];  		//订单返现组
	        $integralInfo = $cacheOrderInfo['integralInfo']; 			//订单积分组
	        $numGroup = $cacheOrderInfo['numGroup']; 				//订单数量组
	        $couponInfo = $cacheOrderInfo['couponInfo'];			//优惠券信息
	        $balanceInfo = $cacheOrderInfo['balanceInfo'];			//赠送余额信息
	        $amountInfo = $cacheOrderInfo['amountInfo'];			//余额信息
	        $activityInfo = $cacheOrderInfo['activityInfo'];				//满减活动信息
	        $shopInfo = $cacheOrderInfo['shopInfo'];						//当前店铺信息
			
	        //TODO 需要保存的订单信息
	        $payPrice = $priceGroup['payPrice'];    									//订单应付价格
			$couponPrice = 0;  																//优惠券价格
			$deductPrice = 0;  																//抵扣价格
            $useIntegral = $integralInfo['useIntegral'];	   			 			//使用积分
            $useGiftBalance = $balanceInfo['deductPrice'];	   			 		//使用赠送余额
            $useBalance = $amountInfo['deductPrice'];	   			 			//使用余额
            $gainIntegral = 0; 																//获得积分
            $gainCoupons = ''; 																//获得优惠券
            $gainGift = ''; 																		//获得优惠券
            $shopId =  $shopInfo['id'] ?: 0;												//店铺id
			$cartIds =  join(",",array_column($cartInfo, 'id'));					//购物车id
			$goods_ids =  join(",",array_column($cartInfo, 'goods_id'));	//商品ids
			$specs_ids =  join(",",array_column($cartInfo, 'specs_id'));		 //规格ids
			$addressDetail='';																	//地址明细
			$orderNo = $this-> setOrderNoAttr();									//订单编号
			$deliveryType = $billId > 0 ? 0 : $cacheOrderInfo['deliveryType'];	//配送方式
			
			//TODO 获取地址信息
			if ( $billId <= 0 ) {
				if ( !$address = $cacheOrderInfo['addressInfo'] ){
					\Db::rollback();
					throw new \think\Exception('地址错误!');
		        }
				$addressDetail = $address['province'].$address['city'].$address['district'].$address['detail'];
	        } else {
	            $vipInfo = model('user_vip')->where('uid',$userInfo['id'])->field('phone,name')->find();
	            if($vipInfo){
	            	$address['contacts'] = $vipInfo['name'];  
	            	$address['phone'] = $vipInfo['phone'];
	            }else{
	            	$vipInfo =  model('user')->where('id',$userInfo['id'])->field('nickname,phone')->find();
	            	$address['contacts'] = $vipInfo['nickname'] ?? "未知";  
	            	$address['phone'] = $vipInfo['phone'] ?? "未知";
	            }
	        }
			
			
			//TODO 使用优惠券
			if( $couponInfo = $cacheOrderInfo['couponInfo'] ){
                if( !model('couponUser')->useCoupon( $couponInfo['id'] ) ){
                	\Db::rollback();
                	throw new \think\Exception('使用优惠劵失败,优惠券已过期或失效！');
                }
                $couponPrice = $couponInfo['price'];
            }
			
			
			//TODO 使用积分抵扣
            if ( $useIntegral && $integralInfo['deductPrice'] >0 && $userInfo['integral'] >= $useIntegral ) {
            	$res = model('User')->useIntegral($uid,$useIntegral,$integralInfo['deductPrice'],$orderNo);
				if (!$res) {
					\Db::rollback();
					throw new \think\Exception('使用积分抵扣失败!');
				}
            }elseif($useIntegral && $integralInfo['deductPrice'] > 0){
            	\Db::rollback();
            	throw new \think\Exception('当前用户积分不足,请重新下单!');
            }
            
            
            //TODO 使用赠送余额抵扣
            if ($useGiftBalance && $useGiftBalance>0 && $userInfo['balance_gift'] >= $useGiftBalance){
                $res = model('User')->useBalanceGift($uid,$useGiftBalance,$useGiftBalance,$orderNo);
				if (!$res) {
					\Db::rollback();
					throw new \think\Exception('使用赠送余额失败!');
				}
            }elseif($useGiftBalance && $useGiftBalance > 0){
            	\Db::rollback();
            	throw new \think\Exception('当前用户赠送余额不足,请重新下单!');
            }
            
            //TODO 使用余额抵扣
            if ($useBalance && $useBalance>0 && $userInfo['balance'] >= $useBalance ) {
            	$res = model('User')->useBalance($uid,$useBalance,$orderNo);
				if (!$res) {
					\Db::rollback();
					throw new \think\Exception('使用余额失败!');
				}
            }elseif($useBalance && $useBalance > 0){
            	\Db::rollback();
            	throw new \think\Exception('当前用户余额不足,请重新下单!');
            }
            
			//TODO 订单保存数据
			unset($cacheOrderInfo['couponList']);
			$saleOldPrice = $priceGroup['totalSaleOldPrice'];
			$salePrice = $priceGroup['totalSalePrice'];
			$goodsType = $cartInfo[0]['goods']['goods_type'];
			$isIntegralGift = $cartInfo[0]['goods']['is_integral_gift'];
			$type = $isIntegralGift == 1 ? -1 : ($goodsType > 0 && $goodsType < 3 ? $goodsType : 0);
			$orderInfo = [
				'uid'            				=> $uid,
				'order_no'            		=> $orderNo,
				'type' 						=> $type,
                'shop_id'         			=> $shopId,
                'user_name'       		=> $address['contacts'],
                'user_phone'      		=> $address['phone'],
                'user_address'    		=> $addressDetail,
                'goods_num'       		=> $numGroup['goodsCount'],
                'total_old_price'   		=> $priceGroup['totalOldPrice'],
                'total_cost_price'   	=> $priceGroup['totalCostPrice'],
                'total_sale_old_price'=> $saleOldPrice,
                'total_sale_price'   	=> $salePrice,
                'freight_price'   			=> $priceGroup['freightPrice'] ?: 0,
                'discount_price'			=> round($saleOldPrice - $salePrice,2),
                'total_price'     			=> $priceGroup['totalPrice'],
                'use_integral'    		=> $useIntegral,
                'use_integral_price'   => $integralInfo['deductPrice'],
                'use_balance'    		=> $useBalance,
                'use_git_balance'    	=> $useGiftBalance,
                'use_activity_price'   	=> $activityInfo['deductPrice'],
                'use_offline_price'   	=> $payType == 'offline' ? round($payPrice - $useBalance,2) : 0,
                'coupon_price'    		=> $couponInfo['price'] ?? 0,
                'coupon_id'    			=> $couponInfo['id'] ?? 0,
                'deduct_price' 			=> $priceGroup['deductPrice'],
                'pay_price'      			=> $payPrice < 0 ? 0 : $payPrice,
                'pay_type'        			=> $payType,
                'remark'            		=> htmlspecialchars($mark),
                'delivery_type'   		=> $deliveryType,
                'info'							=> $cacheOrderInfo,
                'is_pay'						=> 0,
                'status'						=> ($billId > 0 && $payType == 'offline')  ? 3 : 0,
                'bill_id'						=> $billId,			//开单人id
                'bill_identity'				=> $billIdentity,	//开单人身份
                'refund_status'			=> 0,
                'is_del'						=> 0,
            ];
            $orderInfo['brokerage'] = model('User')->backOrderBrokerage($orderInfo,false);
            
            //如果是线下开单
            if($billId > 0 && $payType == 'offline'){
            	if($orderInfo['brokerage'] > $shopInfo['balance']){
            		throw new \think\Exception('当前店铺余额不足支付该笔订单佣金，无法开单！');
            	}
            }
            
            //TODO 余额付款
			if(	$payType == 'balance' && $orderInfo['pay_price'] > $userInfo['balance']){
				\Db::rollback();
				throw new \think\Exception('余额不足，请选择其他支付方式！');
			}
				
			//TODO 佣金付款	
			if(	$payType =='brokerage' && $orderInfo['pay_price'] > $userInfo['brokerage']){
				\Db::rollback();
				throw new \think\Exception('佣金不足，请选择其他支付方式！');
			}
			
			//TODO 创建订单	
			if(	!$order = self::create($orderInfo) ){
				\Db::rollback();
				throw new \think\Exception('订单生成失败！');
			}
			
			//TODO 1.保存订单商品列表
			//TODO 2.减库存加销量
			$res = true;
			$goodsList=[];
			foreach($cartInfo as $key => $value){ 
				//1商品
				$goods = $value['goods']; unset($goods['id']);
				$goods['num'] = $value['cart_num'];  $goods['order_id'] = $order->id;
				$goodsList[] = $goods;	
				//2库存
				$res = $res && model('GoodsSpecs')->decStock($value['specs_id'],$shopId,$value['cart_num']);
			}
			if(	!$res ){
				\Db::rollback();
				throw new \think\Exception('库存不足！');
			}
			
			//TODO 保存订单商品信息
			$res = $res && $order->goodsList()->allowField(true)->saveAll($goodsList);
			//TODO 购物车状态修改
			$res = $res && model('shopCart')->where('id','in',$cartIds)->delete();
			//是否成功
			if(	!$res ){
				\Db::rollback();
				throw new \think\Exception('订单生成失败！');
			}
			
			//提交
			self::clearCacheOrderInfo($orderKey);
			\Db::commit();
			
			//返回订单信息
			$order['add_time'] = date("Y-m-d H:i:s");
			$order['coupon_info'] = $couponInfo;
			
			return  $this->tidyOrder($order);
			
		} catch (\Exception $e) {
			\Db::rollback();
			throw new \think\Exception( $e->getMessage() );
		}
    }
	
	/**
     * 佣金支付
     * @param $order_id
     */
    public  function brokeragePay($orderId)
    {
        $orderInfo = self::getOrderDetail($orderId);
        if ($orderInfo['is_pay'] != 0) {
        	throw new \think\Exception('该订单已支付！');
		}
		$userInfo = request()->userInfo;
		if ($userInfo['brokerage'] < $orderInfo['pay_price']){
        	throw new \think\Exception('佣金不足！');
        }
        $res = model('User')->useBrokerage($userInfo['id'],$orderInfo['pay_price'],$orderInfo['order_no']);
        return $res && $res = self::paySuccess($orderInfo['order_no'], 'brokerage');
    }

 	/**
     * 余额支付
     * @param $order_id
     */
    public  function balancePay($orderId)
    {
    	$orderInfo = self::getOrderDetail($orderId);
        if ($orderInfo['is_pay'] != 0) {
        	throw new \think\Exception('该订单已支付！');
		}
		$userInfo = request()->userInfo;
		if ($userInfo['balance'] < $orderInfo['pay_price']){
			throw new \think\Exception('余额不足！');
        }
        $user = model('User');
        \Db::startTrans();
        $res = $user->useBalance($userInfo['id'],$orderInfo['pay_price'],$orderInfo['order_no']);
        $res && $res = self::paySuccess($orderInfo['order_no'], 'balance');
        if($res){
         	\Db::commit();
       	}else{
       		\Db::rollback();
       	}
        return $res;
    }
	
	 /**
     * TODO 订单支付成功
     * @return bool
     */
    public static function paySuccess($orderNo,$paytype = 'wx',$transaction_id='')
    {
		\Db::startTrans();
		$orderInfo = self::where('order_no', $orderNo )->find();
		if ( $orderInfo->is_pay !== 0 ){
        	return true;
        }
       
		//一.添加账单
		if( $paytype == 'alipay' || $paytype == 'wx' ){
			$price = $orderInfo['pay_price'];
			$msg = ($paytype =='alipay' ? '支付宝支付': '微信支付').floatval($price).'元';
			$uid = $orderInfo['uid']; $unique = $orderInfo['order_no'];
			model('UserBill')->expend('订单支付',$uid,$paytype,'pay_goods',$price,$unique,'0',$msg);
    	}
    
    	//二.循环订单商品 - 发放套餐，项目信息
		foreach($orderInfo['info']['cartInfo'] as $key => $value){
			$goods =  $value['goods'];
			$cart_num =  $value['cart_num'] ?: 1;
        	//一.套餐类型处理
        	if($goods['goods_type'] == 1){
        		for ($i=1; $i<=$cart_num; $i++){
	        		$meal = model('UserYgMeal');
		        	$meal ->order_no = $orderInfo->order_no;
		        	$meal ->shop_id = $orderInfo->shop_id;
		        	$meal ->uid = $orderInfo->uid;
		        	$meal ->effective_time = $goods['effective_time'];
		        	$meal ->goods_id = $goods['goods_id'];
		        	$meal ->specs_id = $goods['specs_id'];
		        	$meal ->sale_price = $goods['sale_price'];
		        	$meal->save();
		        	$ygProj = [];
		        	foreach($goods['proj_list'] as $k => $val){
		        		$ygProj[] = [
		        			'meal_id'=>$meal->id,
		        			'order_no' => $orderInfo->order_no,
		        			'shop_id'	=> $orderInfo->shop_id,
			        		'uid'=>$orderInfo->uid,
			        		'goods_id'=>$val['goods_id'],
			        		'specs_id'=>$val['specs_id'],
			        		'num'=>$val['num'],
			        		'effective_time'=>$meal ->effective_time
			        	];
		        	}
		        	$meal->ygProj()->saveAll($ygProj);
				}
        	}
        	//二.服务类型处理
        	if($goods['goods_type'] == 2){
        		$proj = model('UserYgProj');
	        	$proj ->order_no = $orderInfo->order_no;
	        	$proj ->shop_id = $orderInfo->shop_id;
	        	$proj ->uid = $orderInfo->uid;
	        	$proj ->goods_id = $value['goods_id'];
	        	$proj ->specs_id = $value['specs_id'];
	        	$proj ->num = $cart_num;
	        	$proj ->effective_time = '';
	        	$proj->save();
        	}
			//购买等级升级商品的处理
			if( $goods['is_gm_upgrade'] == 1 && $goods['upgrade_level']){
				model("user_vip")->upgradeLevel($orderInfo->uid,$goods['upgrade_level']);
			}
        }
        
        //自提商品 - 下单之后直接显示在待收货列表
        if( $orderInfo->delivery_type !=1 ){
        	$orderInfo->status = 1;
        }

    	//套餐类 ,服务类, 直接完成
    	if($orderInfo['type'] == 2 || $orderInfo['type'] == 1){
    		$orderInfo->status = 3;
    	}
    	
    	//如果是手机开单，则直接完成
    	if( $orderInfo['bill_id'] > 0 ){
        	$orderInfo->status = 3;
        }
		
		//四，更改为支付状态
		$orderInfo->is_pay = 1;
		$orderInfo->pay_time = date("Y-m-d H:i:s");
		$orderInfo->pay_type = $paytype;
		$orderInfo->transaction_id = $transaction_id;
		if( !$orderInfo->save() ){
			return fasle;
		}	
		
		//TODO 订单付款成功事件
		event('OrderPaySuccess', $orderInfo);
		
		\Db::commit();
        return true;
    }
	
	/**
     * 订单发货
     * @return type
     */
	public function send($data)
    {
    	$validate = new Validate;
		$validate->rule([
			'id'=>'require|integer',
			'delivery_type'=>'require|integer|in:1,2,3',
			'delivery_id'=>'requireIf:delivery_type,1',
	    	'delivery_name' => 'requireIf:delivery_type,1',
	    	'delivery_img' => 'requireIf:delivery_type,2|requireIf:delivery_type,3'
		]);
        if( !$validate->check($data) ) {
        	throw new \think\Exception($validate->getError());
        }
		if(!$order = self::get($data['id'])){
			throw new \think\Exception("找不到该订单！");
		}
		if($order->status !=  0){
			throw new \think\Exception("该订单不是待发货状态，不允许发货！");
		}
		$order->status = 1;
		$order->delivery_type = $data['delivery_type'];
		$order->delivery_id = $data['delivery_id'];
		$order->delivery_name = $data['delivery_name'];
		$order->delivery_img = $data['delivery_img'];
		$order->delivery_time = date("Y-m-d H:i:s");
		$res = $order->save();
		$res && event('UserOrderSeed', $order);
		return $res;
    }
	
	/**
    * 获取订单评论
    * @return type
    */
	public function comment($id)
    {
		if(!$order = self::get($id)){
			throw new \think\Exception("找不到该订单！");
		}
		return $order->commentList;
    }
	
	/**
     * 删除订单
     * @param $uni
     * @param $uid
     * @return bool
     */
    public  function removeOrder($orderId){
        $order = self::getOrderDetail($orderId);
        $statusType = $order['_status']['_type'];
        if ( $statusType != 0 && $statusType != -2 && $statusType != 4){
        	throw new \think\Exception("当前订单状态无法删除！");
        }
        if ( false !== self::where('id',$order['id'])->update(['is_del' => 1]) ) {
            //未支付和已退款的状态下才可以退积分退库存退优惠券
            if ($statusType == 0 || $statusType == -2) {
            	self::regressionIntegral($order);
            	self::regressionStock($order);
            	self::regressionCoupon($order);
            }
            event('UserOrderRemoved', $order);
            return true;
        } else{
        	throw new \think\Exception("订单删除失败！");
        }
    }
	
	/**
     * 取消订单
     * @param string order_id 订单id
     * @param $uid
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public  function cancelOrder($orderId)
    {
        $order = self::getOrderDetail($orderId);
        if ($order['_status']['_type'] != 0) {
        	throw new \think\Exception("该订单状态不能取消！");
        }
        \Db::startTrans();
        try {
            $res = self::regressionIntegral($order) && self::regressionStock($order) 
           				&& self::regressionCoupon($order);
            $order->is_del = 1;
            if ( $res && $order->save() ) {
                \Db::commit();
                return true;
            } else{
            	throw new \think\Exception('异常错误！');
            }
        } catch (\Exception $e) {
            \Db::rollback();
			throw new \think\Exception( $e->getMessage() );
        }
    }
	
	 /**
     * TODO 用户确认收货
     * @param $uni
     * @param $uid
     */
    public  function takeOrder($orderId)
    {
        $order = self::getOrderDetail($orderId);
        if ($order['_status']['_type'] != 2) {
        	throw new \think\Exception("当前订单状态不允许该操作！");
        }
        \Db::startTrans();
		$order->status = 3;
		$order->receive_time =date("Y-m-d H:i:s");
        if ( $order->save() )  {
            try {
				//事件订阅-收货
				event('UserOrderTake',$order);
				//提交事务
				\Db::commit();
				return true;
            } catch (\Exception $e) {
                \Db::rollback();
				throw new \think\Exception( $e->getMessage() );
            }
        } else {
           \Db::rollback();
            return false;
        }
    }
    
	/**
     * 用户申请退款
     * @param $uni
     * @param $uid
     * @param string $refundReasonWap
     * @return bool
     */
    public function orderApplyRefund($orderId,$wap= '',$explain= '',$img = '',$type='',$price=0)
    {
    	if ($type != '退货退款' && $type != '退款无需退货') {
        	throw new \think\Exception("退款类型错误!");
        }
        $order = self::getOrderDetail($orderId);
		if ($order['is_pay'] != 1){
			throw new \think\Exception("该订单未支付，不能申请退款！");
        }
		if ($order['refund_status'] == 1) {
			throw new \think\Exception("正在申请退款中！");
        }
        if ($order['refund_status'] == 2) {
            throw new \think\Exception("已经退款！");
        }
        if ($order['status'] == 1 && $type = '退款无需退货'){
        	throw new \think\Exception("已发货，请收货后申请退货退款！");
        }
        $res = false !== self::where('id',$order['id'])->update([
	        'refund_status' => 1, 
	        'refund_apply_time' => date("Y-m-d H:i:s"), 	 //申请退款时间：1
	        'refund_type' => $type, 	 //退款类型：1
	        'refund_wap' => $wap, 	 //前台退款原因
	        'refund_explain' => $explain,  //退款用户说明
	        'refund_img' =>$img, //退款图片
	        'refund_price' =>$price //退款价格
        ]);
		event('UserOrderApplyRefund', $order);
		if(!$res){
			throw new \think\Exception("申请退款失败!");
		}
		return true;
    }
	
	 /**
     * 驳回申请退款
     * @param $uni
     * @param $uid
     * @param string $refundReasonWap
     * @return bool
     */
    public  function rejectApply($id,$desc)
    {
    	$orderInfo = self::getOrderDetail($id);
		if($orderInfo['refund_status'] != 1){
			throw new \think\Exception("订单未申请退款!");
		}
    	$orderInfo->refund_status = '-1';
    	$orderInfo->refund_reason = $desc;
		$orderInfo->save();
        return true;
    }
	
	 /**
     * 退款
     * @param $uni
     * @param $uid
     * @param string $refundReasonWap
     * @return bool
     */
    public  function refund($id,$index=1)
    {
		$orderInfo = self::getOrderDetail($id);
		
		if($index == 1){
			if($orderInfo['refund_status'] != 1){
				throw new \think\Exception("订单未申请退款!");
			}
			if($orderInfo['refund_status'] == 2){
				throw new \think\Exception("该订单已退款!");
			}
		}
		
		//临时变量
		$orderUid = $orderInfo['uid'];
		$orderShopId = $orderInfo['shop_id'];
		$orderUserInfo = model('User')->getInfo($orderUid);
		$orderShopInfo = model('shop')->get($orderShopId);
		$filed = $orderInfo['pay_type'] == 'brokerage' ? 'brokerage' : 'balance';
		
		//开启事务
		\Db::startTrans();
		
		//添加流水账
		//商家，只有已收货的才会入账，所以退款时，要判断是否已收货再减余额
		$res = true;
		if($orderInfo['status'] > 1){
			$res = model('Shop')->where('id',$orderShopId)->setDec('balance',$refund_price);
			$res = $res && model('ShopBill')->expend('订单退款',$orderUid,$orderShopId,$filed, 'order_refund', $refund_price, $orderInfo['order_no'], $orderShopInfo['balance'] - $refund_price, '用户订单退款支出' . floatval($refund_price) . '元');
		}
		$res = $res && model('UserBill')->income('订单退款',$orderUid,$filed,'order_refund', $refund_price, $orderInfo['order_no'],bcadd($orderUserInfo['balance'], $refund_price,2),'订单退款获得'.floatval($refund_price).'元');
        if(!$res) {
        	\Db::rollback();
        	throw new \think\Exception("退款失败!");
        }
		
		//退款到用户
        if($orderInfo['pay_type'] == 'wx' ){
            try{
                WxApi::payOrderRefund($order_no,$refund_price,'wx_h5');
            }catch(\Exception $e){
            	\Db::rollback();
            	throw new \think\Exception( $e->getMessage() );
            }
        }else if($orderInfo['pay_type'] == 'wx_applets' ){
            try{
                WxApi::payOrderRefund($order_no,$refund_price,'wx_applets');
            }catch(\Exception $e){
            	\Db::rollback();
            	throw new \think\Exception( $e->getMessage() );
            }
        }else if($orderInfo['pay_type'] == 'wx_h5'){
            try{
            	WxApi::payOrderRefund($order_no,$refund_price,'wx_h5');
            }catch(\Exception $e){
            	\Db::rollback();
            	throw new \think\Exception( $e->getMessage() );
            }
        }else if($orderInfo['pay_type'] == 'alipay'){
            try{
            	AliPayApi::payOrderRefund($order_no,$refund_price);
            }catch(\Exception $e){
            	\Db::rollback();
            	throw new \think\Exception( $e->getMessage() );
            }
        }else if($orderInfo['pay_type'] == 'balance'){//余额
            if(!$orderUserInfo){
                \Db::rollback();
            	throw new \think\Exception('订单用户不存在!');
            }
			$res = model('user')->where('id',$orderUid)->setInc('balance',$refund_price);
			if(!$res) {
	        	\Db::rollback();
	        	throw new \think\Exception('退款失败!');
	        }
        }else if($orderInfo['pay_type'] == 'brokerage'){//佣金
            if(!$orderUserInfo){
            	\Db::rollback();
	        	throw new \think\Exception('订单用户不存在!');
            }
			$res = model('user')->where('id',$orderUid)->setInc('brokerage',$refund_price);
			if(!$res) {
	        	\Db::rollback();
				throw new \think\Exception('退款失败!');
	        }
        }else{
        	\Db::rollback();
        	throw new \think\Exception('付款类型错误!');
        }
		
		//更新为已退款状态
		$orderInfo->status = '-1';
    	$orderInfo->refund_status = 2;
    	$orderInfo->refund_time = date("Y-m-d H:i:s");
    	$orderInfo->refund_price = $refund_price;
		$res = $orderInfo->save($orderInfo);
        if($res){
			if( $orderInfo['is_customized']==1 && $orderInfo['is_pay'] == 1 ){
				//return $this->refund($id,2);
			}
			\Db::commit();
            return true;
        }else{
        	\Db::rollback();
        	throw new \think\Exception('退款失败!');
        }
		
    }
	
	
	//-----------------------------------
	//-----------定时任务↓--------------
	//-----------------------------------
	 /**
     * 未支付订单自动取消
     */
    public static function orderUnpaidCancel()
    {
        //系统预设取消订单时间段
		$order_cancel_time =  getSystem("buess_order_pay_time") ?? 0;
		
		if(!$order_cancel_time) return true;
		
        //检查是否有未支付的订单   未支付查询条件
        $orderList = self::where('is_pay', 0)->where('is_del', 0)
        	->where('status', 0)
        	->where('refund_status', 0)
        	->field('*')
        	->select();
        if (empty($orderList)) return true;
        try {
            $res = true;
            foreach ($orderList as $order) {
               $res = $res && self::regressionAll($order_cancel_time, $order);
            }
            if (!$res) throw new \Exception('更新错误');
            unset($orderList, $res);
            return true;
        } catch (PDOException $e) {
            Log::error('未支付自动取消时发生数据库查询错误，错误原因为：' . $e->getMessage());
            throw new \Exception($e->getMessage());
        } catch (\think\Exception $e) {
            Log::error('未支付自动取消时发生系统错误，错误原因为：' . $e->getMessage());
            throw new \Exception($e->getMessage());
        }

    }
	
	/**
     * 自动收货 
     * @return bool
     */
    public static function startTakeOrder()
    {
    	//0为取消自动收货功能
        $systemTime = getSystem("buess_order_receive_time") ?? 0;
        if ($systemTime == 0) return true;
		
		//时间
        $sevenDay = date("Y-m-d H:i:s", time() - $systemTime *24*60*60 );
		
        $model = new self;
        $model = $model->alias('o');
        $model = $model->where('o.is_pay', 1);
        $model = $model->where('o.status', 1);
        $model = $model->where('o.refund_status', 0);
        $model = $model->where('o.delivery_time', 'lt', $sevenDay);
        $model = $model->where('o.delivery_time','<>','');
        $model = $model->where('o.is_del', 0);
        $orderInfo = $model->column('id', 'id');
        if (!count($orderInfo)) return true;
		
        foreach ($orderInfo as $key => $order_id) {
            $order = self::get($order_id);
            $order->status = 3;
			$order->receive_time =date("Y-m-d H:i:s");
			$order->save();
        }
		
		return true;
    }
}
